package monitor

import (
	"fmt"
	"strings"
	"sync"
	"time"

	"health-check/internal/config"
	"health-check/internal/logger"
	"health-check/internal/notification"
	"health-check/internal/process"
)

// MonitorManager 监控管理器
type MonitorManager struct {
	config         *config.Config
	processMonitor *process.ProcessMonitor
	notifier       *notification.NotificationManager
	mu             sync.RWMutex
	running        bool
	stopCh         chan struct{}
	wg             sync.WaitGroup
}

// NewMonitorManager 创建监控管理器
func NewMonitorManager(cfg *config.Config) *MonitorManager {
	return &MonitorManager{
		config: cfg,
		processMonitor: process.NewProcessMonitorWithConfig(
			cfg.Global.RetryCount,
			cfg.Global.RetryDelay,
		),
		notifier: notification.NewNotificationManager(&cfg.Notify),
		stopCh:   make(chan struct{}),
	}
}

// Start 启动监控
func (mm *MonitorManager) Start() error {
	mm.mu.Lock()
	defer mm.mu.Unlock()

	if mm.running {
		return fmt.Errorf("监控器已经在运行中")
	}

	mm.running = true
	mm.stopCh = make(chan struct{})

	// 启动进程监控
	enabledProcesses := mm.config.GetEnabledProcesses()
	for _, procConfig := range enabledProcesses {
		mm.wg.Add(1)
		go mm.monitorProcess(procConfig)
	}

	logger.Infof("监控器已启动，监控 %d 个进程", len(enabledProcesses))

	return nil
}

// Stop 停止监控
func (mm *MonitorManager) Stop() {
	mm.mu.Lock()
	defer mm.mu.Unlock()

	if !mm.running {
		return
	}

	mm.running = false
	close(mm.stopCh)
	mm.wg.Wait()

	logger.Info("监控器已停止")
}

// IsRunning 检查是否在运行
func (mm *MonitorManager) IsRunning() bool {
	mm.mu.RLock()
	defer mm.mu.RUnlock()
	return mm.running
}

// monitorProcess 监控单个进程
func (mm *MonitorManager) monitorProcess(procConfig config.ProcessConfig) {
	defer mm.wg.Done()

	ticker := time.NewTicker(procConfig.CheckInterval)
	defer ticker.Stop()

	for {
		select {
		case <-mm.stopCh:
			return
		case <-ticker.C:
			mm.checkProcess(procConfig)
		}
	}
}

// checkProcess 检查进程状态
func (mm *MonitorManager) checkProcess(procConfig config.ProcessConfig) {
	// 添加panic恢复
	defer func() {
		if r := recover(); r != nil {
			logger.Errorf("检查进程 %s 时发生panic: %v", procConfig.Name, r)
		}
	}()

	// 检查是否启用
	if !procConfig.Enabled {
		logger.Debugf("进程 %s 已禁用，跳过检查", procConfig.Name)
		return
	}

	// 检查是否为进程组
	if procConfig.IsGroup {
		mm.checkProcessGroup(procConfig)
		return
	}

	var info *process.ProcessInfo
	var err error

	// 根据配置选择检查方式
	if procConfig.PID > 0 {
		info, err = mm.processMonitor.CheckProcessByPID(procConfig.PID)
	} else if procConfig.Command != "" {
		info, err = mm.processMonitor.CheckProcessByCommand(procConfig.Command)
	} else {
		info, err = mm.processMonitor.CheckProcessByName(procConfig.Name)
	}

	if err != nil {
		logger.Errorf("检查进程 %s 失败: %v", procConfig.Name, err)
		mm.processMonitor.RecordProcessFailure(procConfig.Name)

		// 记录进程历史
		return
	}

	// 记录进程状态
	logger.Debugf("进程 %s: 运行中=%t, PID=%d, CPU=%.2f%%, 内存=%.2f%%",
		info.Name, info.Running, info.PID, info.CPU, info.Memory)

	// 如果进程未运行且启用了自动重启
	if !info.Running && procConfig.AutoRestart {
		mm.processMonitor.RecordProcessFailure(procConfig.Name)

		// 发送进程告警
		if mm.notifier != nil {
			mm.notifier.SendProcessAlert(procConfig.Name, "进程停止", "进程已停止运行，正在尝试重启")
		}

		mm.restartProcess(procConfig)
	} else if info.Running {
		// 进程运行正常，重置失败计数
		mm.processMonitor.RecordProcessSuccess(procConfig.Name)
	}
}

// checkProcessGroup 检查进程组状态
func (mm *MonitorManager) checkProcessGroup(procConfig config.ProcessConfig) {
	// 检查是否启用
	if !procConfig.Enabled {
		logger.Debugf("进程组 %s 已禁用，跳过检查", procConfig.Name)
		return
	}

	// 创建进程组对象
	group := &process.ProcessGroup{
		Name:         procConfig.Name,
		Pattern:      procConfig.GroupPattern,
		Start:        procConfig.GroupStart,
		End:          procConfig.GroupEnd,
		GroupMembers: procConfig.GroupMembers,
		Enabled:      procConfig.Enabled,
		RestartCmd:   procConfig.RestartCmd,
		WorkDir:      procConfig.WorkDir,
		Env:          procConfig.Env,
	}

	// 添加进程组到监控器
	if err := mm.processMonitor.AddProcessGroup(group); err != nil {
		logger.Errorf("添加进程组 %s 失败: %v", procConfig.Name, err)
		return
	}

	// 检查进程组状态
	status, err := mm.processMonitor.CheckProcessGroup(procConfig.Name)
	if err != nil {
		logger.Errorf("检查进程组 %s 失败: %v", procConfig.Name, err)
		return
	}

	// 记录进程组状态
	logger.Infof("进程组 %s: 总数=%d, 运行中=%d, 已停止=%d, 错误=%d, 状态=%s",
		status.GroupName, status.TotalMembers, status.RunningCount,
		status.StoppedCount, status.ErrorCount, status.OverallStatus)

	// 根据整体状态决定是否发送告警
	if status.OverallStatus == "critical" || status.OverallStatus == "warning" {
		mm.processMonitor.RecordProcessGroupFailure(procConfig.Name)

		// 发送进程组告警
		if mm.notifier != nil {
			message := mm.buildProcessGroupMessage(status)
			mm.notifier.SendProcessAlert(procConfig.Name, status.OverallStatus, message)
		}

		// 如果启用了自动重启，尝试重启进程组
		if procConfig.AutoRestart {
			mm.restartProcessGroup(procConfig)
		}
	} else {
		// 进程组状态正常，重置失败计数
		mm.processMonitor.RecordProcessGroupSuccess(procConfig.Name)
	}
}

// restartProcessGroup 重启进程组
func (mm *MonitorManager) restartProcessGroup(procConfig config.ProcessConfig) {
	logger.Infof("尝试重启进程组: %s", procConfig.Name)

	// 获取重启前的状态
	status, err := mm.processMonitor.CheckProcessGroup(procConfig.Name)
	if err != nil {
		logger.Errorf("获取进程组 %s 状态失败: %v", procConfig.Name, err)
	}

	restartedMembers, err := mm.processMonitor.RestartProcessGroup(procConfig.Name)
	if err != nil {
		logger.Errorf("重启进程组 %s 失败: %v", procConfig.Name, err)

		// 发送重启失败告警
		if mm.notifier != nil {
			restartInfo := mm.processMonitor.GetProcessGroupRestartInfo(procConfig.Name)
			message := fmt.Sprintf("进程组 %s 重启失败\n\n错误: %v", procConfig.Name, err)
			if status != nil {
				message += "\n\n" + mm.buildProcessGroupMessage(status)
			}
			if restartInfo != nil {
				message += fmt.Sprintf("\n\n重启统计:\n总重启次数: %d\n首次重启: %s\n最后重启: %s",
					restartInfo.TotalRestartCount,
					restartInfo.FirstRestart.Format("2006-01-02 15:04:05"),
					restartInfo.LastRestart.Format("2006-01-02 15:04:05"))
			}
			mm.notifier.SendProcessRestartAlert(procConfig.Name, 0, message)
		}
	} else {
		logger.Infof("进程组 %s 重启成功", procConfig.Name)

		// 为每个重启成功的子进程单独发送通知
		if mm.notifier != nil && len(restartedMembers) > 0 {
			for _, memberName := range restartedMembers {
				// 获取子进程的详细信息
				info, err := mm.processMonitor.CheckProcessByName(memberName)
				var message string
				if err == nil && info.Running {
					message = fmt.Sprintf("子进程 %s 重启成功\nPID: %d\nCPU: %.1f%%\n内存: %.1f%%",
						memberName, info.PID, info.CPU, info.Memory)
				} else {
					message = fmt.Sprintf("子进程 %s 重启成功", memberName)
				}

				// 发送单个子进程的重启成功通知
				mm.notifier.SendProcessRestartAlert(memberName, 0, message)
			}
		}
	}
}

// restartProcess 重启进程
func (mm *MonitorManager) restartProcess(procConfig config.ProcessConfig) {
	// 添加panic恢复
	defer func() {
		if r := recover(); r != nil {
			logger.Errorf("重启进程 %s 时发生panic: %v", procConfig.Name, r)
		}
	}()

	// 检查是否应该重启
	if !mm.processMonitor.ShouldRestart(procConfig.Name) {
		restartInfo := mm.processMonitor.GetRestartInfo(procConfig.Name)
		if restartInfo != nil {
			logger.Warnf("进程 %s 已达到最大重启次数 (%d)，停止重启",
				procConfig.Name, restartInfo.RestartCount)
		}
		return
	}

	logger.Infof("尝试重启进程: %s", procConfig.Name)

	if procConfig.RestartCmd == "" {
		logger.Warnf("进程 %s 未配置重启命令，跳过重启", procConfig.Name)
		return
	}

	// 执行重启命令
	err := mm.processMonitor.RestartProcess(
		procConfig.Name,
		procConfig.RestartCmd,
		procConfig.WorkDir,
		procConfig.Env,
	)

	if err != nil {
		logger.Errorf("重启进程 %s 失败: %v", procConfig.Name, err)

		// 发送重启失败告警
		restartInfo := mm.processMonitor.GetRestartInfo(procConfig.Name)
		restartCount := 0
		if restartInfo != nil {
			restartCount = restartInfo.RestartCount
		}
		if mm.notifier != nil {
			mm.notifier.SendProcessRestartAlert(procConfig.Name, restartCount, fmt.Sprintf("重启失败: %v", err))
		}
	} else {
		logger.Infof("进程 %s 重启成功", procConfig.Name)

		// 发送重启成功通知
		if mm.notifier != nil {
			// 获取进程信息
			info, err := mm.processMonitor.CheckProcessByName(procConfig.Name)
			var message string
			if err == nil && info.Running {
				message = fmt.Sprintf("进程 %s 重启成功\nPID: %d\nCPU: %.1f%%\n内存: %.1f%%",
					procConfig.Name, info.PID, info.CPU, info.Memory)
			} else {
				message = fmt.Sprintf("进程 %s 重启成功", procConfig.Name)
			}
			mm.notifier.SendProcessRestartAlert(procConfig.Name, 0, message)
		}
	}
}

// GetStatus 获取监控状态
func (mm *MonitorManager) GetStatus() map[string]interface{} {
	mm.mu.RLock()
	defer mm.mu.RUnlock()

	status := map[string]interface{}{
		"running":            mm.running,
		"processes":          len(mm.config.GetEnabledProcesses()),
		"restart_info":       mm.processMonitor.GetAllRestartInfo(),
		"group_restart_info": mm.processMonitor.GetAllProcessGroupRestartInfo(),
		"notification":       mm.notifier.GetStatus(),
	}

	return status
}

// GetProcessMonitor 获取进程监控器
func (mm *MonitorManager) GetProcessMonitor() *process.ProcessMonitor {
	return mm.processMonitor
}

// ReloadConfig 重新加载配置
func (mm *MonitorManager) ReloadConfig(newConfig *config.Config) error {
	mm.mu.Lock()
	defer mm.mu.Unlock()

	// 停止当前监控
	if mm.running {
		mm.running = false
		close(mm.stopCh)
		mm.wg.Wait()
	}

	// 更新配置
	mm.config = newConfig

	// 重新创建通知管理器
	mm.notifier = notification.NewNotificationManager(&newConfig.Notify)

	// 重新创建进程监控器
	mm.processMonitor = process.NewProcessMonitorWithConfig(
		newConfig.Global.RetryCount,
		newConfig.Global.RetryDelay,
	)

	// 重新启动监控
	mm.running = true
	mm.stopCh = make(chan struct{})

	// 启动进程监控
	enabledProcesses := mm.config.GetEnabledProcesses()
	for _, procConfig := range enabledProcesses {
		mm.wg.Add(1)
		go mm.monitorProcess(procConfig)
	}

	logger.Infof("配置已重新加载，监控 %d 个进程", len(enabledProcesses))

	return nil
}

// buildProcessGroupMessage 构建进程组消息
func (mm *MonitorManager) buildProcessGroupMessage(status *process.ProcessGroupStatus) string {
	var message strings.Builder

	// 基本信息
	message.WriteString(fmt.Sprintf("进程组 %s 状态异常\n", status.GroupName))
	message.WriteString(fmt.Sprintf("整体状态: %s\n", status.OverallStatus))
	message.WriteString(fmt.Sprintf("总成员数: %d, 运行中: %d, 已停止: %d, 错误: %d\n\n",
		status.TotalMembers, status.RunningCount, status.StoppedCount, status.ErrorCount))

	// 详细状态
	message.WriteString("成员状态详情:\n")

	// 按状态分组显示
	var running, stopped, error []string

	for _, member := range status.Members {
		switch member.Status {
		case "running":
			running = append(running, fmt.Sprintf("✅ %s (PID: %d, CPU: %.1f%%, 内存: %.1f%%)",
				member.Name, member.PID, member.CPU, member.Memory))
		case "stopped":
			stopped = append(stopped, fmt.Sprintf("❌ %s", member.Name))
		case "error":
			error = append(error, fmt.Sprintf("⚠️ %s - %s", member.Name, member.Error))
		}
	}

	// 显示运行中的进程
	if len(running) > 0 {
		message.WriteString(fmt.Sprintf("运行中 (%d):\n", len(running)))
		for _, item := range running {
			message.WriteString(fmt.Sprintf("  %s\n", item))
		}
		message.WriteString("\n")
	}

	// 显示已停止的进程
	if len(stopped) > 0 {
		message.WriteString(fmt.Sprintf("已停止 (%d):\n", len(stopped)))
		for _, item := range stopped {
			message.WriteString(fmt.Sprintf("  %s\n", item))
		}
		message.WriteString("\n")
	}

	// 显示错误的进程
	if len(error) > 0 {
		message.WriteString(fmt.Sprintf("错误 (%d):\n", len(error)))
		for _, item := range error {
			message.WriteString(fmt.Sprintf("  %s\n", item))
		}
		message.WriteString("\n")
	}

	return message.String()
}

// buildProcessGroupRecoveryMessage 构建进程组恢复消息
func (mm *MonitorManager) buildProcessGroupRecoveryMessage(status *process.ProcessGroupStatus) string {
	var message strings.Builder

	// 基本信息
	message.WriteString(fmt.Sprintf("进程组 %s 已恢复\n", status.GroupName))
	message.WriteString(fmt.Sprintf("整体状态: %s\n", status.OverallStatus))
	message.WriteString(fmt.Sprintf("总成员数: %d, 运行中: %d, 已停止: %d, 错误: %d\n\n",
		status.TotalMembers, status.RunningCount, status.StoppedCount, status.ErrorCount))

	// 显示所有成员状态
	message.WriteString("成员状态:\n")
	for _, member := range status.Members {
		switch member.Status {
		case "running":
			message.WriteString(fmt.Sprintf("✅ %s (PID: %d, CPU: %.1f%%, 内存: %.1f%%)\n",
				member.Name, member.PID, member.CPU, member.Memory))
		case "stopped":
			message.WriteString(fmt.Sprintf("❌ %s\n", member.Name))
		case "error":
			message.WriteString(fmt.Sprintf("⚠️ %s - %s\n", member.Name, member.Error))
		}
	}

	return message.String()
}

// TestAllNotifications 测试所有通知
func (mm *MonitorManager) TestAllNotifications() error {
	return mm.notifier.TestAllNotifications()
}

// GetConfig 获取配置
func (mm *MonitorManager) GetConfig() *config.Config {
	return mm.config
}
